import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';

dayjs.extend(utc);
dayjs.extend(timezone);

interface PrismaWhereCondition {
  [key: string]: any;
}

export function buildPrismaWhere(
  searchForm: Record<string, any>,
  searchOperator: Record<string, string | null>
): PrismaWhereCondition {
  const where: PrismaWhereCondition = {};

  Object.entries(searchForm).forEach(([field, rawValue]) => {
    const operator = searchOperator[field];
    const value = normalizeValue(rawValue, field);

    // 空值过滤策略（三重校验）
    if (!operator || value === null || value === undefined) return;

    // 特殊日期字段处理
    if (isDateField(field)) {
      handleDateTimeWithTimezone(where, field, operator, value);
      return;
    }

    // 通用条件构建
    const condition = buildCondition(operator, value, field);
    if (condition) where[field] = condition;
  });

  return where;

  /** 值标准化处理（带时区支持） */
  function normalizeValue(rawValue: any, field: string): any {
    // 空值直接返回
    if (rawValue === null || rawValue === undefined) return rawValue;

    // 日期字段特殊处理
    if (isDateField(field)) {
      return dayjs(rawValue).isValid() 
        ? rawValue //dayjs.tz(rawValue, 'Asia/Shanghai').toDate()  // 从界面获取的日期字符串与后端postgresql数据库的timestamptz日期格式兼容
        : null;
    }

    // 通用类型转换
    return typeof rawValue === 'string' 
      ? rawValue.trim() 
      : rawValue;
  }

  /** 日期字段判断 */
  function isDateField(field: string): boolean {
    return ['created_at','updated_at','deleted_at', 'start_time', 'end_time'].includes(field);
  }

  /** 带时区的日期处理 */
  function handleDateTimeWithTimezone(
    where: PrismaWhereCondition,
    field: string,
    operator: string,
    value: any
  ) {
    if (operator === 'dateRange' && Array.isArray(value)) {
      where[field] = {
        gte: dayjs.tz(value[0], 'Asia/Shanghai').toDate(),
        lte: dayjs.tz(value[1], 'Asia/Shanghai').toDate()
      };
    } else {
      const condition = buildCondition(operator, value, field);
      if (condition) where[field] = condition;
    }
  }

  /** 条件构建器（增强空值校验） */
  function buildCondition(
    operator: string,
    value: any,
    field?: string
  ): Record<string, any> | null {
    // 空值二次校验
    if (value === '' || value === null) return null;

    switch (operator) {
      case 'equals': return { equals: value };
      case 'not': return { not: value };
      case 'lt': return { lt: castNumber(value, field) };
      case 'lte': return { lte: castNumber(value, field) };
      case 'gt': return { gt: castNumber(value, field) };
      case 'gte': return { gte: castNumber(value, field) };
      case 'contains': return { contains: value, mode: 'insensitive' };
      case 'in': return { in: convertToArray(value) };
      case 'isSet': return value === '' ? { isSet: false } : { isSet: !!value };
      default: return null;
    }
  }

    /** 辅助函数 */
  
    function handleJsonField(where: any, value: any, operator: string): void {
      if (typeof value === 'string') {
        try {
          where.json = operator === 'jsonPath' 
            ? { path: ['$'], equals: JSON.parse(value) } 
            : { equals: JSON.parse(value) };
        } catch (error) {
          console.error('Invalid JSON format:', value);
        }
      }
    }
  
    function handleEmptyStringAsUnset(where: any, value: any): void {
      if (value === '') {
        where.group_id = { isSet: false };
      } else if (value !== null && value !== undefined) {
        where.group_id = { equals: value };
      }
    }
  
    function convertToArray(value: any): any[] {
      return Array.isArray(value)
        ? value
        : String(value).split(',').map(v => {
            const num = Number(v.trim());
            return isNaN(num) ? v.trim() : num;
          });
    }
  
    function castNumber(value: any, field?: string): number | any {
      const num = Number(value);
      return isNaN(num) 
        ? (console.warn(`Invalid number value for field ${field}:`, value), value)
        : num;
    }
}
